package feces.model;

import java.sql.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import feces.utility.Utility;
import feces.validator.NotNullValidator;
import feces.validator.StringValidator;

/**
 * 商品(Product)
 * 
 * @author Bromine0x23
 * @see 5.5.1.2.3
 */
@Entity
@Table(schema = "SCOTT", name = "PRODUCT")
@NoArgsConstructor
public class Product implements IValidatable {

	private static final long serialVersionUID = 7567112185112981117L;

	/**
	 * 商品代码 主键、存储为<b>ID: INTEGER</b>
	 */
	@Id
	@SequenceGenerator(name = "PRODUCT_ID", sequenceName = "PRODUCT_ID", allocationSize = 1)
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PRODUCT_ID")
	@Column(name = "ID", nullable = false)
	@Getter
	private Integer id;

	/**
	 * 商品名称 非空、存储为<b>NAME: NVARCHAR2(40)</b>
	 */
	@Column(name = "NAME", nullable = false, length = 40)
	@Getter
	@Setter
	private String name;

	/**
	 * 商品一级分类 外键、非空、存储
	 * 
	 * <pre>
	 * major_type.getId()
	 * </pre>
	 * 
	 * 于<b>MAJOR_TYPE_ID: INTEGER</b>
	 */
	@OneToOne
	@JoinColumn(name = "MAJOR_TYPE_ID", nullable = false)
	@Getter
	private ProductMajorType majorType;

	/**
	 * 商品二级分类 外键、非空、存储
	 * 
	 * <pre>
	 * minor_type.getId()
	 * </pre>
	 * 
	 * 于<b>MINOR_TYPE_ID: INTEGER</b>
	 */
	@OneToOne
	@JoinColumn(name = "MINOR_TYPE_ID", nullable = false)
	@Getter
	private ProductMinorType minorType;

	/**
	 * 计量单位 非空、存储为<b>UNIT: NVARCHAR2(10)</b>
	 */
	@Column(name = "UNIT", nullable = false)
	@Getter
	@Setter
	private String unit;

	/**
	 * 原价 非空、存储为<b>PRICE: NUMBER(15, 2)</b>
	 */
	@Column(name = "PRICE", nullable = false, precision = 15, scale = 2)
	@Getter
	@Setter
	private Double price;

	/**
	 * 折扣 非空、默认值为100.00、存储为<b>DISCOUNT: NUMBER(5, 2)</b>
	 */
	@Column(name = "DISCOUNT", nullable = false)
	@Getter
	@Setter
	private Double discount;

	/**
	 * 成本 非空、存储为<b>COST: NUMBER(15, 2)</b>
	 */
	@Column(name = "COST", nullable = false)
	@Getter
	@Setter
	private Double cost;

	/**
	 * 型号 存储为<b>TYPE: NVARCHAR2(10)</b>
	 */
	@Column(name = "TYPE")
	@Getter
	@Setter
	private String type;

	/**
	 * 供应商 外键、存储为<b>SUPPLIER_ID: INTEGER</b>
	 */
	@OneToOne
	@JoinColumn(name = "SUPPLIER_ID", nullable = false)
	@Getter
	@Setter
	private Supplier supplier;

	/**
	 * 厂商 非空、存储为<b>PRODUCTOR: NVARCHAR2(30)</b>
	 */
	@Column(name = "PRODUCTOR", nullable = false)
	@Getter
	@Setter
	private String productor;

	/**
	 * 保质期限 非空、存储为<b>PERIOD: DATE</b>
	 */
	@Column(name = "PERIOD", nullable = false)
	@Getter
	@Setter
	private Date period;

	/**
	 * 是否可退货 非空、默认为false、存储为<b>RETURNABLE: NUMBER(1)</b>
	 */
	@Column(name = "RETURNABLE", nullable = false, columnDefinition = "CHAR(1)")
	private Character returnable;

	/**
	 * 是否可换货 非空、默认为false、存储为<b>CHANGABLE: NUMBER(1)</b>
	 */
	@Column(name = "CHANGABLE", nullable = false, columnDefinition = "CHAR(1)")
	private Character changable;

	/**
	 * 备注 存储为<b>REMARK: NVARCHAR2(200)</b>
	 */
	@Column(name = "REMARK", nullable = false)
	@Getter
	@Setter
	private String remark;
	
	/**
	 * @param minorType 新的minorType
	 */
	public void setMinorType(ProductMinorType minorType) {
		this.minorType = minorType;
		this.majorType = minorType.getMajorType();
	}
	
	/**
	 * @return 可否退货
	 */
	public Boolean isReturnable() {
		return Utility.toBoolean(returnable);
	}

	/**
	 * @param returnable 新的可否退货状态
	 */
	public void setReturnable(Boolean returnable) {
		this.returnable = Utility.toCharacter(returnable);
	}

	/**
	 * @return 可否换货
	 */
	public Boolean isChangable() {
		return Utility.toBoolean(changable);
	}

	/**
	 * @param changable 新的可否换货状态
	 */
	public void setChangable(Boolean changable) {
		this.changable = Utility.toCharacter(changable);
	}

	@Override
	public boolean isValid() {
		return StringValidator.validate(getName(), 40) && NotNullValidator.validate(getMajorType())
				&& NotNullValidator.validate(getMinorType()) && getMinorType().isValid()
				&& StringValidator.validate(getUnit(), 10) && NotNullValidator.validate(getPrice())
				&& NotNullValidator.validate(getDiscount()) && NotNullValidator.validate(getCost())
				&& StringValidator.validate(getType(), 10, true) && NotNullValidator.validate(getSupplier())
				&& getSupplier().isValid() && NotNullValidator.validate(getPeriod())
				&& StringValidator.validate(getRemark(), 200, true);
	}

}
